#include "CheckWin.h"
#include <algorithm>
#include <iostream>

CheckWin::CheckWin(const std::vector<Chess>& analyseChessVec)
    : m_analyseChessVec(analyseChessVec)
{
    std::sort(m_analyseChessVec.begin(), m_analyseChessVec.end());
}

CheckWin::CheckWin(const std::vector<Chess>& analyseChessVec, const Chess& chess)
    : m_analyseChessVec(analyseChessVec)
{
    m_analyseChessVec.push_back(chess);
    std::sort(m_analyseChessVec.begin(), m_analyseChessVec.end());
}

CheckWin::~CheckWin()
{
    m_analyseChessVec.clear();
}

bool CheckWin::analyseChess2Win(std::vector<KindChess>& resualtVec)
{
    std::vector<Chess> ddChess = findDDChess();
    for (size_t i = 0; i < ddChess.size(); i++)
    {
        if (analyseChess(resualtVec, ddChess.at(i)))
        {
            return true;
        }
    }
    return false;
}

const std::vector<Chess> CheckWin::findDDChess()
{
    std::vector<Chess> ddChess;
    for (size_t i = 0; i < m_analyseChessVec.size(); i++)
    {
        short cunt = std::count(m_analyseChessVec.begin() + i, m_analyseChessVec.end(),
            m_analyseChessVec.at(i));

        if (cunt > 1)
        {
            ddChess.push_back(m_analyseChessVec.at(i));
            i = i + cunt - 1;
        }
    }
    return ddChess;
}

bool CheckWin::analyseChess(std::vector<KindChess>& resualtVec, const Chess& eye)
{
    resualtVec.clear();
    std::list<Chess> tmpChessLst;
    for (size_t i = 0; i < m_analyseChessVec.size(); i++)
    {
        tmpChessLst.push_back(m_analyseChessVec.at(i));
    }
    checkEyeChess(tmpChessLst, eye, resualtVec);
    if (checkEEEChess(tmpChessLst, resualtVec))
    {
        return true;
    }
    return checkABCChess(tmpChessLst, resualtVec);
}

void CheckWin::checkEyeChess(std::list<Chess>& tmpChessLst, const Chess& eyeChess, std::vector<KindChess>& resualtVec)
{
    std::list<Chess>::iterator iter1 = std::find(tmpChessLst.begin(), tmpChessLst.end(), eyeChess);
    KindChess kindWeave = {};
    kindWeave.type = ChessStatus::EYE;

    kindWeave.item.push_back(Chess(*iter1));
    tmpChessLst.erase(iter1);

    std::list<Chess>::iterator iter2 = std::find(tmpChessLst.begin(), tmpChessLst.end(), eyeChess);

    kindWeave.item.push_back(Chess(*iter2));
    tmpChessLst.erase(iter2);
    resualtVec.push_back(kindWeave);
}

bool CheckWin::checkEEEChess(std::list<Chess>& tmpChessLst, std::vector<KindChess>& resualtVec)
{
    std::list<Chess> tmpLst;
    while (true)
    {
        std::list<Chess>::iterator iter = tmpChessLst.begin();
        if (iter == tmpChessLst.end())
        {
            break;
        }
        Chess findChess(*iter);
        short cunt = std::count(tmpChessLst.begin(), tmpChessLst.end(), findChess);
        if (cunt == 3)
        {
            KindChess kindWeave = {};
            kindWeave.type = ChessStatus::EEE;
            kindWeave.item.push_back(Chess(*iter));
            tmpChessLst.erase(iter);

            std::list<Chess>::iterator finditer1 =
                std::find(tmpChessLst.begin(), tmpChessLst.end(), findChess);
            kindWeave.item.push_back(Chess(*finditer1));
            tmpChessLst.erase(finditer1);

            std::list<Chess>::iterator finditer2 =
                std::find(tmpChessLst.begin(), tmpChessLst.end(), findChess);
            kindWeave.item.push_back(Chess(*finditer2));
            tmpChessLst.erase(finditer2);
            resualtVec.push_back(kindWeave);
        }
        else
        {
            tmpLst.push_back(Chess(*iter));
            tmpChessLst.erase(iter);
        }
    }
    tmpChessLst.swap(tmpLst);
    return tmpChessLst.empty();
}

bool CheckWin::checkABCChess(std::list<Chess>& tmpChessLst, std::vector<KindChess>& resualtVec)
{
    std::list<Chess> tmpLst;
    while (true)
    {
        std::list<Chess>::iterator iter = tmpChessLst.begin();
        if (iter == tmpChessLst.end())
        {
            break;
        }

        std::list<Chess>::iterator finditer1 =
            std::find(tmpChessLst.begin(), tmpChessLst.end(), Chess(iter->type, iter->count + 1));

        std::list<Chess>::iterator finditer2 =
            std::find(tmpChessLst.begin(), tmpChessLst.end(), Chess(iter->type, iter->count + 2));

        if (finditer1 != tmpChessLst.end() &&
            finditer2 != tmpChessLst.end())
        {
            KindChess kindWeave = {};
            kindWeave.type = ChessStatus::SHUN;
            kindWeave.item.push_back(Chess(*iter));
            kindWeave.item.push_back(Chess(*finditer1));
            kindWeave.item.push_back(Chess(*finditer2));
            tmpChessLst.erase(iter);
            tmpChessLst.erase(finditer1);
            tmpChessLst.erase(finditer2);
            resualtVec.push_back(kindWeave);
        }
        else
        {
            tmpLst.push_back(Chess(*iter));
            tmpChessLst.erase(iter);
        }
    }

    tmpChessLst.swap(tmpLst);
    return tmpChessLst.empty();
}
